package com.qingyun.cameralab.preview_capture

import android.content.Context
import androidx.camera.core.AspectRatio
import androidx.camera.core.AspectRatio.Ratio
import androidx.camera.core.CameraSelector
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView
import androidx.core.content.ContextCompat
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner

class CameraPreviewManager private constructor(private val builder: Builder) :
    DefaultLifecycleObserver {
    private val context: Context = builder.context
    private val previewView: PreviewView
    private var lensFacing: Int
    private val aspectRatio: Int
    private var cameraProvider: ProcessCameraProvider? = null

    init {
        previewView = builder.previewView
        lensFacing = builder.lensFacing
        aspectRatio = builder.aspectRatio
    }

    override fun onResume(owner: LifecycleOwner) {
        startPreview()
    }

    fun startPreview() {
        if (PermissionHelper.hasCameraPermission(context)) {
            initializeCamera()
        } else {
            builder.permissionCallback?.onPermissionRequired()
        }
    }

    override fun onPause(owner: LifecycleOwner) {
        stopPreview()
    }

    fun stopPreview() {
        cameraProvider?.unbindAll()
    }

    fun switchCamera() {
        val newLensFacing = if (lensFacing == CameraSelector.LENS_FACING_FRONT) {
            CameraSelector.LENS_FACING_BACK
        } else {
            CameraSelector.LENS_FACING_FRONT
        }
        lensFacing = newLensFacing
        startPreview()
    }

    private fun adjustPreviewScaling() {
        previewView.scaleType = PreviewView.ScaleType.FILL_CENTER
        previewView.implementationMode = PreviewView.ImplementationMode.COMPATIBLE
    }

    private fun initializeCamera() {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(context)
        cameraProviderFuture.addListener({
            cameraProvider = cameraProviderFuture.get()
            //创建预览配置
            val preview = Preview.Builder()
                .setTargetAspectRatio(aspectRatio)
                .build()
                .also {
                    it.setSurfaceProvider(previewView.surfaceProvider)
                }
            //创建相机选择器
            val cameraSelector = CameraSelector.Builder()
                .requireLensFacing(lensFacing)
                .build()
            try {
                //取消所有用例
                cameraProvider?.unbindAll()
                cameraProvider?.bindToLifecycle(builder.lifecycleOwner, cameraSelector, preview)
                adjustPreviewScaling()
                builder.callback?.onCameraOpened()
            } catch (e: Exception) {
                builder.callback?.onCameraError(e)
            }
        }, ContextCompat.getMainExecutor(context))
    }

    class Builder(val context: Context) {
        lateinit var previewView: PreviewView
        lateinit var lifecycleOwner: LifecycleOwner
        var lensFacing: Int = CameraSelector.LENS_FACING_BACK
        var aspectRatio: Int = AspectRatio.RATIO_16_9
        var callback: CameraCallback? = null
        var permissionCallback: PermissionCallback? = null
        fun setPreviewView(previewView: PreviewView): Builder {
            this.previewView = previewView
            return this
        }

        fun setLifecycleObserver(owner: LifecycleOwner): Builder {
            this.lifecycleOwner = owner
            return this
        }

        fun setLensFacing(facing: Int): Builder {
            this.lensFacing = facing
            return this
        }

        fun setAspectRatio(@Ratio ratio: Int): Builder {
            this.aspectRatio = ratio
            return this
        }

        fun setCallback(callback: CameraCallback?): Builder {
            this.callback = callback
            return this
        }

        fun setPermissionCallback(permissionCallback: PermissionCallback?): Builder {
            this.permissionCallback = permissionCallback
            return this
        }

        fun build(): CameraPreviewManager {
            require(::previewView.isInitialized) { "previewView must be set" }
            require(::lifecycleOwner.isInitialized) { "lifecycleObserver must be set" }
            return CameraPreviewManager(this).apply {
                lifecycleOwner.lifecycle.addObserver(this)
            }
        }
    }

    interface CameraCallback {
        fun onCameraOpened()
        fun onCameraError(e: Exception)
    }

    interface PermissionCallback {
        fun onPermissionRequired()
    }
}